import httpx
from typing import Optional
from app.config import settings
from app.utils.logger import logger
import json

class QwenVLService:
    def __init__(self):
        # Qwen3-VL API配置
        self.api_url = settings.QWEN_API_URL
        self.model_name = settings.QWEN_MODEL_NAME
        self.timeout = float(settings.QWEN_TIMEOUT)  # 从配置读取超时时间
        self.max_video_size_mb = settings.QWEN_MAX_VIDEO_SIZE_MB
        
    async def analyze_video_by_url(self, video_url: str, prompt: str) -> str:
        """使用Qwen3-VL通过视频URL分析视频"""
        try:
            logger.info(f"开始调用Qwen3-VL分析视频: {video_url}")
            
            # 检查视频大小
            try:
                async with httpx.AsyncClient(timeout=10.0) as client:
                    head_response = await client.head(video_url)
                    if head_response.status_code == 200:
                        content_length = head_response.headers.get('content-length')
                        if content_length:
                            video_size_mb = int(content_length) / (1024 * 1024)
                            logger.info(f"视频大小: {video_size_mb:.2f} MB")
                            
                            # 如果视频太大，给出警告或拒绝
                            if video_size_mb > self.max_video_size_mb:
                                raise Exception(f"视频文件过大 ({video_size_mb:.2f} MB)，超过限制 ({self.max_video_size_mb} MB)")
                            elif video_size_mb > 10:
                                logger.warning(f"视频文件较大 ({video_size_mb:.2f} MB)，可能需要较长处理时间")
            except Exception as size_check_error:
                logger.warning(f"无法检查视频大小: {size_check_error}")
            
            # 构建请求数据，按照你提供的格式
            request_data = {
                "prompt": prompt,
                "model": self.model_name,
                "videos": [video_url],
                "stream": False
            }
            
            # 构建请求头
            headers = {
                "Content-Type": "application/json",
                "Accept": "*/*",
                "Connection": "keep-alive"
            }
            
            logger.info(f"发送Qwen3-VL请求: {json.dumps(request_data, ensure_ascii=False)}")
            
            # 发送请求
            async with httpx.AsyncClient(timeout=self.timeout) as client:
                response = await client.post(
                    self.api_url,
                    json=request_data,
                    headers=headers
                )
                
                logger.info(f"Qwen3-VL响应状态: {response.status_code}")
                
                logger.info(f"Qwen3-VL响应状态码: {response.status_code}")
                logger.info(f"Qwen3-VL响应头: {dict(response.headers)}")
                
                if response.status_code == 200:
                    try:
                        result = response.json()
                        logger.info(f"Qwen3-VL响应JSON: {json.dumps(result, ensure_ascii=False, indent=2)}")
                        
                        # 额外记录响应内容的详细信息
                        logger.info(f"Qwen3-VL响应数据类型: {type(result)}")
                        if isinstance(result, dict):
                            logger.info(f"Qwen3-VL响应字段: {list(result.keys())}")
                        
                        # 根据实际返回格式提取结果
                        if isinstance(result, dict):
                            # 如果返回是字典，尝试提取文本内容
                            if "response" in result:
                                analysis_text = result["response"]
                            elif "text" in result:
                                analysis_text = result["text"]
                            elif "content" in result:
                                analysis_text = result["content"]
                            elif "output" in result:
                                analysis_text = result["output"]
                            elif "data" in result:
                                analysis_text = result["data"]
                            elif "result" in result:
                                analysis_text = result["result"]
                            else:
                                # 如果没有找到预期字段，返回整个结果的字符串形式
                                logger.warning(f"未找到预期的响应字段，返回完整结果。可用字段: {list(result.keys())}")
                                analysis_text = json.dumps(result, ensure_ascii=False, indent=2)
                        elif isinstance(result, str):
                            analysis_text = result
                        else:
                            analysis_text = str(result)
                        
                        # 统一规范响应：有些服务返回 list，或用 Markdown 代码块包裹 JSON
                        if isinstance(analysis_text, list):
                            merged_parts = [x for x in analysis_text if isinstance(x, str) and x.strip()]
                            analysis_text = "\n".join(merged_parts)
                        if isinstance(analysis_text, (dict, list)):
                            try:
                                analysis_text = json.dumps(analysis_text, ensure_ascii=False, indent=2)
                            except Exception:
                                analysis_text = str(analysis_text)
                        if isinstance(analysis_text, str):
                            text = analysis_text.strip()
                            # 去除 ``` 或 ```json 包裹
                            if text.startswith("```") and text.endswith("```"):
                                lines = analysis_text.splitlines()
                                if lines and lines[0].lstrip().startswith("```"):
                                    lines = lines[1:]
                                if lines and lines[-1].rstrip().startswith("```"):
                                    lines = lines[:-1]
                                analysis_text = "\n".join(lines).strip()
                            # 若为 JSON 字符串，尝试规范化
                            try:
                                parsed = json.loads(analysis_text)
                                analysis_text = json.dumps(parsed, ensure_ascii=False, indent=2)
                            except Exception:
                                pass
                        
                        # 若主体内容为空，兼容 done_reason 作为可读提示
                        if isinstance(analysis_text, str) and not analysis_text.strip():
                            dr = result.get('done_reason')
                            if isinstance(dr, str) and dr.strip():
                                analysis_text = f"分析失败原因: {dr}"
                        
                        # 最终保证为字符串
                        if not isinstance(analysis_text, str):
                            analysis_text = str(analysis_text)
                        
                        logger.info(f"Qwen3-VL分析完成，结果长度: {len(analysis_text)}")
                        logger.info(f"Qwen3-VL分析结果内容: {analysis_text}")
                        return analysis_text
                    except json.JSONDecodeError as e:
                        # 如果不是JSON格式，直接返回文本
                        response_text = response.text
                        logger.info(f"Qwen3-VL返回非JSON格式，直接使用文本: {response_text[:500]}...")
                        logger.info(f"Qwen3-VL完整响应文本: {response_text}")
                        return response_text
                        
                else:
                    error_msg = f"Qwen3-VL API调用失败: {response.status_code}"
                    response_text = response.text
                    logger.error(f"{error_msg}")
                    logger.error(f"响应内容: {response_text}")
                    raise Exception(f"{error_msg} - {response_text}")
                    
        except httpx.TimeoutException as e:
            # 从video_url中提取视频ID和分段信息
            video_info = self._extract_video_info_from_url(video_url)
            logger.error(f"Qwen3-VL真正超时(>{self.timeout}秒): {video_info} - {str(e)}")
            raise Exception(f"请求超时(>{self.timeout}秒): {video_info} - {str(e)}")
        except httpx.ConnectError as e:
            video_info = self._extract_video_info_from_url(video_url)
            logger.error(f"Qwen3-VL连接错误: {video_info} - {str(e)}")
            raise Exception(f"连接失败，请检查Qwen3-VL服务是否运行: {video_info} - {str(e)}")
        except httpx.HTTPStatusError as e:
            video_info = self._extract_video_info_from_url(video_url)
            logger.error(f"Qwen3-VL HTTP状态错误: {video_info} - 状态码: {e.response.status_code}")
            logger.error(f"响应内容: {e.response.text}")
            raise Exception(f"HTTP错误({e.response.status_code}): {video_info} - {e.response.text}")
        except httpx.RequestError as e:
            video_info = self._extract_video_info_from_url(video_url)
            logger.error(f"Qwen3-VL请求错误: {video_info} - {type(e).__name__}: {str(e)}")
            raise Exception(f"请求错误: {video_info} - {type(e).__name__}: {str(e)}")
        except Exception as e:
            video_info = self._extract_video_info_from_url(video_url)
            logger.error(f"Qwen3-VL未知错误: {video_info} - {type(e).__name__}: {str(e)}")
            import traceback
            logger.error(f"详细错误堆栈: {traceback.format_exc()}")
            raise Exception(f"未知错误: {video_info} - {type(e).__name__}: {str(e)}")
    
    async def test_connection(self) -> bool:
        """测试Qwen3-VL API连接"""
        try:
            logger.info(f"测试Qwen3-VL连接: {self.api_url}")
            
            # 使用一个简单的测试请求
            test_data = {
                "prompt": "测试连接",
                "model": self.model_name,
                "videos": ["http://example.com/test.mp4"],  # 测试URL
                "stream": False
            }
            
            headers = {
                "Content-Type": "application/json",
                "Accept": "*/*",
                "Connection": "keep-alive"
            }
            
            async with httpx.AsyncClient(timeout=10.0) as client:
                response = await client.post(
                    self.api_url,
                    json=test_data,
                    headers=headers
                )
                
                # 即使返回错误，只要能连接到服务就算成功
                logger.info(f"Qwen3-VL连接测试响应: {response.status_code}")
                return response.status_code in [200, 400, 422]  # 400/422可能是参数错误，但连接正常
                
        except Exception as e:
            logger.error(f"Qwen3-VL连接测试失败: {str(e)}")
            return False
    
    async def analyze_text(self, prompt: str) -> str:
        """使用Qwen模型分析纯文本内容"""
        try:
            logger.info("开始调用Qwen模型分析文本")
            
            # 构建请求数据（纯文本分析，不包含视频）
            request_data = {
                "prompt": prompt,
                "model": self.model_name,
                "stream": False
            }
            
            # 构建请求头
            headers = {
                "Content-Type": "application/json",
                "Accept": "*/*",
                "Connection": "keep-alive"
            }
            
            # 发送请求
            async with httpx.AsyncClient(timeout=self.timeout) as client:
                logger.info(f"发送文本分析请求到: {self.api_url}")
                
                response = await client.post(
                    self.api_url,
                    json=request_data,
                    headers=headers
                )
                
                logger.info(f"Qwen文本分析响应状态: {response.status_code}")
                
                if response.status_code == 200:
                    result = response.json()
                    logger.info(f"Qwen文本分析响应JSON: {json.dumps(result, ensure_ascii=False, indent=2)}")
                    logger.info(f"Qwen文本分析响应数据类型: {type(result)}")
                    if isinstance(result, dict):
                        logger.info(f"Qwen文本分析响应字段: {list(result.keys())}")
                    
                    # 提取分析结果
                    if 'choices' in result and len(result['choices']) > 0:
                        analysis_result = result['choices'][0].get('message', {}).get('content', '')
                        if analysis_result:
                            logger.info("Qwen文本分析成功")
                            logger.info(f"Qwen文本分析结果长度: {len(analysis_result)}")
                            logger.info(f"Qwen文本分析结果内容: {analysis_result}")
                            return analysis_result.strip()
                    
                    # 如果没有找到标准格式，尝试其他可能的字段
                    if 'output' in result:
                        output = result['output']
                        if isinstance(output, str):
                            logger.info(f"Qwen文本分析使用output字段: {output}")
                            return output.strip()
                        elif isinstance(output, dict) and 'text' in output:
                            logger.info(f"Qwen文本分析使用output.text字段: {output['text']}")
                            return output['text'].strip()

                    # 兼容 response 字段为字符串或字符串列表的返回格式
                    if 'response' in result:
                        response_payload = result['response']
                        if isinstance(response_payload, list):
                            merged_text = "\n".join(
                                item.strip()
                                for item in response_payload
                                if isinstance(item, str) and item.strip()
                            )
                            if merged_text:
                                logger.info("Qwen文本分析使用response列表字段")
                                return merged_text.strip()
                        elif isinstance(response_payload, str) and response_payload.strip():
                            logger.info("Qwen文本分析使用response字段")
                            return response_payload.strip()
                    
                    logger.warning(f"Qwen文本分析响应格式异常: {result}")
                    return "文本分析完成，但响应格式异常"
                else:
                    error_msg = f"Qwen文本分析失败，状态码: {response.status_code}"
                    try:
                        error_detail = response.json()
                        error_msg += f"，错误详情: {error_detail}"
                    except:
                        error_msg += f"，响应内容: {response.text}"
                    
                    logger.error(error_msg)
                    raise Exception(error_msg)
                    
        except httpx.TimeoutException:
            error_msg = f"Qwen文本分析超时 (>{self.timeout}秒)"
            logger.error(error_msg)
            raise Exception(error_msg)
        except Exception as e:
            logger.error(f"Qwen文本分析异常: {str(e)}")
            raise Exception(f"文本分析失败: {str(e)}")
    
    def _extract_video_info_from_url(self, video_url: str) -> str:
        """从视频URL中提取视频ID和分段信息"""
        try:
            # URL格式: http://192.168.210.72:8000/videos/segments/{video_id}/{segment_filename}
            # 或者: http://192.168.210.72:8000/videos/{filename}
            
            if "/videos/segments/" in video_url:
                # 分段视频
                parts = video_url.split("/videos/segments/")
                if len(parts) > 1:
                    segment_path = parts[1]  # video_id/segment_filename
                    path_parts = segment_path.split("/")
                    if len(path_parts) >= 2:
                        video_id = path_parts[0]
                        segment_filename = path_parts[1]
                        return f"视频ID: {video_id[:8]}..., 分段: {segment_filename}"
                    else:
                        return f"分段路径: {segment_path}"
            elif "/videos/" in video_url:
                # 完整视频
                parts = video_url.split("/videos/")
                if len(parts) > 1:
                    filename = parts[1]
                    return f"完整视频: {filename}"
            
            # 如果无法解析，返回URL的最后部分
            return f"视频URL: {video_url.split('/')[-1]}"
            
        except Exception:
            # 解析失败时返回简化的URL信息
            return f"视频URL: {video_url.split('/')[-1] if '/' in video_url else video_url}"
    
    async def get_service_info(self) -> dict:
        """获取服务信息"""
        return {
            "service_name": "Qwen3-VL",
            "api_url": self.api_url,
            "model_name": self.model_name,
            "timeout": self.timeout,
            "status": "active"
        }